package com.flexrrb.controls
{
	import com.flexrrb.controls.amazingDateChooserClasses.DateChooserModes;
	
	import flash.display.DisplayObject;
	import flash.display.Graphics;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.utils.describeType;
	import flash.utils.getQualifiedClassName;
	
	import mx.controls.Button;
	import mx.controls.DateChooser;
	import mx.controls.LinkButton;
	import mx.controls.Text;
	import mx.core.IFlexDisplayObject;
	import mx.core.IUITextField;
	import mx.core.UIComponent;
	import mx.core.UITextField;
	import mx.events.FlexEvent;
	import mx.skins.halo.DateChooserIndicator;
	import mx.styles.CSSStyleDeclaration;
	import mx.styles.ISimpleStyleClient;
	import mx.styles.StyleManager;

	public class AmazingDateChooser extends UIComponent
	{
		public function AmazingDateChooser()
		{
			super();
			//var selector:CSSStyleDeclaration=StyleManager.getStyleDeclaration("AmazingDateChooser");
			//StyleManager.setStyleDeclaration("AmazingDateChooser", selector, false);

			this.width=200;
			this.height=200;
			addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
			addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
			addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler);
		}

		[Bindable]
		[Embed(source="/assets/leftArrow.png")]
		public static var leftArrow:Class;
		[Bindable]
		[Embed(source="/assets/rightArrow.png")]
		public static var rightArrow:Class;

		private var monthArray:Array=["Jan", "Feb", "March", "April", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"];

		private var todayDate:Date=new Date();

		private var dayBlocksArray:Array=new Array();
		private var monthBlocksArray:Array=[];
		private var yearBlocksArray:Array=[];
		private var decadeBlocksArray:Array=[];
		private var selectionIndicator:Array=[];

		private var todayIndicator:IFlexDisplayObject;

		private var rollOverIndicator:IFlexDisplayObject;

		private var displayedMode:String=DateChooserModes.DATE;

		private var dayNames:Array=["S", "M", "T", "W", "T", "F", "S"];

		private var dateGrid:UIComponent;
		private var monthGrid:UIComponent;
		private var yearGrid:UIComponent;
		private var decadeGrid:UIComponent;

		private var headerLeftNavButton:Button;
		private var headerRightNavButton:Button;
		private var headerMiddleNavButton:LinkButton;
		private var cellHeight:Number=14;

		private var cellWidth:Number=14;
		private var yOffset:Number=-1;
		private var headerContaner:UIComponent;

		private var background:UIComponent;
		private var border:UIComponent;

		private var _firstDayOfWeek:int=0;

		[Inspectable(category="General", defaultValue="0")]

		public function get firstDayOfWeek():int
		{
			return _firstDayOfWeek;
		}

		public function set firstDayOfWeek(value:int):void
		{
			if (value < 0 || value > 6)
				return;

			if (value == _firstDayOfWeek)
				return;

			_firstDayOfWeek=value;
			//dayNamesChanged=true;
			//selectedMonthYearChanged=true;

			//invalidateProperties();
		}

		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			super.updateDisplayList(unscaledWidth, unscaledHeight);

			var borderThickness:Number=getStyle("borderThickness");
			var cornerRadius:Number=getStyle("cornerRadius");
			var borderColor:Number=getStyle("borderColor");

			var w:Number=unscaledWidth - borderThickness * 2;
			var h:Number=unscaledHeight - borderThickness * 2;

			var g:Graphics=background.graphics;
			g.clear();
			g.beginFill(0xFFFFFF);
			g.drawRoundRect(0, 0, w, h, cornerRadius * 2, cornerRadius * 2);
			g.endFill();
			background.visible=true;

			g=border.graphics;
			g.clear();
			g.beginFill(borderColor);
			g.drawRoundRect(0, 0, unscaledWidth, unscaledHeight, cornerRadius * 2, cornerRadius * 2);
			g.endFill();
			var bgColor:uint=StyleManager.NOT_A_COLOR;
			bgColor=getStyle("backgroundColor");
			if (bgColor == StyleManager.NOT_A_COLOR)
				bgColor=0xFFFFFF;
			var bgAlpha:Number=1;
			bgAlpha=getStyle("backgroundAlpha");
			g.beginFill(bgColor, bgAlpha);
			g.drawRoundRect(borderThickness, borderThickness, w, h, cornerRadius > 0 ? (cornerRadius - 1) * 2 : 0, cornerRadius > 0 ? (cornerRadius - 1) * 2 : 0);
			g.endFill();
			border.visible=true;

			dateGrid.setActualSize(unscaledWidth, unscaledHeight - headerContaner.height);

			var paddingLeft:Number=getStyle("paddingLeft");
			var paddingRight:Number=getStyle("paddingRight");
			var paddingBottom:Number=getStyle("paddingBottom");
			var paddingTop:Number=getStyle("paddingTop");

			var blockX:Number=paddingLeft;

			// Bug 134794, clip height/width so that RTE's are not thrown
			cellWidth=Math.max((unscaledWidth - (paddingLeft + paddingRight)) / 7, 4);
			cellHeight=Math.max((unscaledHeight - paddingBottom) / 7, 4);

			if (displayedMode == DateChooserModes.DATE)
			{
				displayDateLayout();
				dateGrid.visible=true;
				monthGrid.visible=false;
				yearGrid.visible=false;
				decadeGrid.visible=false;
			}
			else if (displayedMode == DateChooserModes.MONTH)
			{
				dateGrid.visible=false;
				monthGrid.visible=true;
				yearGrid.visible=false;
				decadeGrid.visible=false;
			}
			else if (displayedMode == DateChooserModes.YEAR)
			{
				dateGrid.visible=false;
				monthGrid.visible=false;
				yearGrid.visible=true;
				decadeGrid.visible=false;
			}
			else if (displayedMode == DateChooserModes.DECADE)
			{
				dateGrid.visible=false;
				monthGrid.visible=false;
				yearGrid.visible=false;
				decadeGrid.visible=true;
			}
			var labelPosition:Number=paddingTop;
			//var blockX:Number=10;

			for (var columnIndex:int=0; columnIndex < 7; columnIndex++)
			{
				for (var rowIndex:int=0; rowIndex < 7; rowIndex++)
				{
					var label:IUITextField=dayBlocksArray[columnIndex][rowIndex];
					if (rowIndex == 0)
						labelPosition=paddingTop;
					else
						labelPosition+=cellHeight;

					label.setActualSize(cellWidth, cellHeight);
					label.move(blockX, labelPosition);
				}
				blockX+=cellWidth;
			}

			dateGrid.move(10, 30);
			monthGrid.move(10, 30);
			yearGrid.move(10, 30);
			decadeGrid.move(10, 30);
			headerContaner.width=this.width;
			headerContaner.height=25;

			headerLeftNavButton.width=30;
			headerLeftNavButton.height=20;
			headerRightNavButton.move(headerContaner.width - headerLeftNavButton.width, 0);

			headerRightNavButton.width=30;
			headerRightNavButton.height=20;
			headerLeftNavButton.move(0, 0);

			headerMiddleNavButton.height=20;
			headerMiddleNavButton.move((headerContaner.width / 2) - headerMiddleNavButton.width, 0);
			rollOverIndicator.setActualSize(cellWidth, cellHeight);
			headerContaner.move(0, 0);

		}

		override protected function createChildren():void
		{
			super.createChildren();
			if (!background)
			{
				background=new UIComponent();
				addChild(background);
				UIComponent(background).styleName=this;
			}
			if (!border)
			{
				border=new UIComponent();
				addChild(border);
				UIComponent(border).styleName=this;
			}

			createHeader();
			createDayLayout();
			createMonthLayout();
			createYearLayout();
			createDecadeLayout();
			//createTodayButton();
			//createTodayIndicator();
			//createSelectionIndicator();
			//createRollOverIndicator();
		}

		private function displayDateLayout():void
		{
			var days:Array=getDaysForMonthAndYear(todayDate.getFullYear(), todayDate.getMonth());
			var firstDay:Number=findFirstDayOfMonth(todayDate.getFullYear(), todayDate.getMonth());
			var dayNumber:int;
			var columnIndex:int; // 0 - 6
			var rowIndex:int=1; // 1 - 6
			var i:int;
			var offset:int=getOffsetOfMonth(todayDate.getFullYear(), todayDate.getMonth());
			var daysInMonth:int=getNumberOfDaysInMonth(todayDate.getFullYear(), todayDate.getMonth());
			for (columnIndex=0; columnIndex < offset; columnIndex++)
			{
				dayBlocksArray[columnIndex][rowIndex].text="";
			}
			for (dayNumber=1; dayNumber <= daysInMonth; dayNumber++)
			{
				i=offset + dayNumber - 1;
				columnIndex=i % 7;
				rowIndex=1 + Math.floor(i / 7);

				var todayLabel:IUITextField=dayBlocksArray[columnIndex][rowIndex];
				todayLabel.text=dayNumber.toString();
			}
			drawDayNames();
			headerMiddleNavButton.label=monthArray[todayDate.getMonth()] + "," + todayDate.getFullYear();
		}

		private function drawDayNames():void
		{
			for (var columnIndex:int=0; columnIndex < 7; columnIndex++)
			{
				var dayOfWeek:int=(columnIndex + firstDayOfWeek) % 7;
				var dayName:String=dayNames ? dayNames[dayOfWeek] : "";
				dayBlocksArray[columnIndex][0].text=dayName;
			}
		}

		private function displayMonthLayout():void
		{

		}

		private function displayYearLayout():void
		{

		}

		private function displayDecadeLayout():void
		{

		}

		private function createHeader():void
		{
			//if(!leftNavButton)
			/*var leftNavButton:Button=new Button();
			   leftNavButton.height=this.height - 25;
			   leftNavButton.width=10;
			   leftNavButton.setStyle("icon", leftArrow);
			   leftNavButton.setStyle("cornerRadius", 0);
			   leftNavButton.setStyle("fillAlphas", [1, 1, 1, 1]);

			   var rightNavButton:Button=new Button();
			   rightNavButton.height=this.height - 25;
			   rightNavButton.width=10;
			   rightNavButton.setStyle("icon", rightArrow);
			   rightNavButton.setStyle("cornerRadius", 0);
			   rightNavButton.setStyle("fillAlphas", [1, 1, 1, 1]);

			   this.addChild(leftNavButton);
			   this.addChild(rightNavButton);

			   leftNavButton.addEventListener(MouseEvent.CLICK, leftButtonHandler);
			   rightNavButton.addEventListener(MouseEvent.CLICK, rightButtonHandler);
			   leftNavButton.move(0, 25);
			 rightNavButton.move(this.width - 10, 25);*/
			if (!headerContaner)
			{
				headerContaner=new UIComponent();
				headerContaner.setStyle("backgroundColor", "0xCC99CC");


				headerLeftNavButton=new Button();

				headerLeftNavButton.setStyle("icon", leftArrow);
				headerLeftNavButton.setStyle("cornerRadius", 10);
				headerLeftNavButton.setStyle("fillAlphas", [1, 1, 1, 1]);
				headerLeftNavButton.autoRepeat=true;
				headerLeftNavButton.addEventListener(FlexEvent.BUTTON_DOWN, leftButtonHandler);
				headerContaner.addChild(headerLeftNavButton);

				headerMiddleNavButton=new LinkButton();
				headerMiddleNavButton.addEventListener(MouseEvent.CLICK, middleButtonHandler);
				headerContaner.addChild(headerMiddleNavButton);

				headerRightNavButton=new Button();

				headerRightNavButton.setStyle("icon", rightArrow);
				headerRightNavButton.setStyle("cornerRadius", 10);
				headerRightNavButton.setStyle("fillAlphas", [1, 1, 1, 1]);
				headerRightNavButton.autoRepeat=true;
				headerRightNavButton.addEventListener(FlexEvent.BUTTON_DOWN, rightButtonHandler);
				headerContaner.addChild(headerRightNavButton);

				this.addChild(headerContaner);
			}
		}

		private function createDayLayout():void
		{
			if (!dateGrid)
			{
				dateGrid=new UIComponent();
				addChild(dateGrid);
			}
			for (var columnIndex:int=0; columnIndex < 7; columnIndex++)
			{
				dayBlocksArray[columnIndex]=[];

				for (var rowIndex:int=0; rowIndex < 7; rowIndex++)
				{
					var label:IUITextField=IUITextField(createInFontContext(UITextField));
					dayBlocksArray[columnIndex][rowIndex]=label;
					label.selectable=false;
					label.ignorePadding=true;

					dateGrid.addChild(DisplayObject(label));
				}
			}

			if (!rollOverIndicator)
			{
				var rollOverIndicatorClass:Class=getStyle("rollOverIndicatorSkin");
				if (!rollOverIndicatorClass)
					rollOverIndicatorClass=DateChooserIndicator;
				rollOverIndicator=IFlexDisplayObject(new rollOverIndicatorClass());
				// too lazy to make an interface for this.
				/*if (isDateChooserIndicator(rollOverIndicator))
				 Object(rollOverIndicator).indicatorColor="rollOverColor";*/
				if (rollOverIndicator is ISimpleStyleClient)
					ISimpleStyleClient(rollOverIndicator).styleName=this;
				addChildAt(DisplayObject(rollOverIndicator), 0);
				rollOverIndicator.visible=false;
			}
		}

		private function createMonthLayout():void
		{
			if (!monthGrid)
			{
				monthGrid=new UIComponent();
				addChild(monthGrid);
			}
			var cols:Number=4;
			var rows:Number=3;
			var locX:Number=5;
			var locY:Number=2;
			var lblHeight:Number=50;
			var lblWidth:Number=45;
			var currentMonth:Number=0;
			for (var i:int=0; i < rows; i++)
			{
				for (var j:int=0; j < cols; j++)
				{
					var lbl:LinkButton=new LinkButton();
					lbl.label=monthArray[currentMonth];
					lbl.name=currentMonth.toString();
					monthGrid.addChild(lbl);
					lbl.addEventListener(MouseEvent.CLICK, monthClickHandler);
					lbl.move(locX, locY);
					locX+=lblWidth;
					if (currentMonth == todayDate.getMonth())
					{
						lbl.setStyle("color", "0x0000FF");
					}
					currentMonth++;
				}
				locY+=lblHeight;
				locX=5;
			}
			headerMiddleNavButton.label=todayDate.getFullYear().toString();
		}

		private function createYearLayout():void
		{
			if (!yearGrid)
			{
				yearGrid=new UIComponent();
				addChild(yearGrid);
			}
			var cols:Number=4;
			var rows:Number=3;
			var locX:Number=5;
			var locY:Number=2;
			var lblHeight:Number=50;
			var lblWidth:Number=45;
			var currentYear:Number=(todayDate.getFullYear() - (todayDate.getFullYear() % 10)) - 1;
			for (var i:int=0; i < rows; i++)
			{
				for (var j:int=0; j < cols; j++)
				{
					var lbl:LinkButton=new LinkButton();
					lbl.label=currentYear.toString();
					//lbl.name=String(i + j);
					yearGrid.addChild(lbl);
					lbl.addEventListener(MouseEvent.CLICK, yearClickHandler);
					lbl.move(locX, locY);
					locX+=lblWidth;
					if (currentYear == todayDate.getFullYear())
					{
						lbl.setStyle("color", "0x0000FF");
					}
					currentYear++;
				}
				locY+=lblHeight;
				locX=5;
			}
			headerMiddleNavButton.label=(todayDate.getFullYear() - (todayDate.getFullYear() % 10)) + "-" + ((todayDate.getFullYear() - (todayDate.getFullYear() % 10)) + 10);
		}

		private function createDecadeLayout():void
		{
			if (!decadeGrid)
			{
				decadeGrid=new UIComponent();
				addChild(decadeGrid);
			}
			var cols:Number=4;
			var rows:Number=3;
			var locX:Number=5;
			var locY:Number=2;
			var lblHeight:Number=50;
			var lblWidth:Number=45;
			var currentDecade:Number=(todayDate.getFullYear() - (todayDate.getFullYear() % 100));
			for (var i:int=0; i < rows; i++)
			{
				for (var j:int=0; j < cols; j++)
				{
					var lbl:Text=new Text();
					lbl.selectable=false;
					lbl.setStyle("fontWeight", "bold");
					lbl.htmlText=currentDecade.toString() + "-\n" + (currentDecade + 9);
					lbl.name=currentDecade.toString();
					decadeGrid.addChild(lbl);
					lbl.addEventListener(MouseEvent.CLICK, decadeClickHandler);
					lbl.move(locX, locY);
					locX+=lblWidth;
					if (currentDecade == todayDate.getFullYear())
					{
						lbl.setStyle("color", "0x0000FF");
					}
					currentDecade+=10;
				}
				locY+=lblHeight;
				locX=5;
			}
			headerMiddleNavButton.label=(todayDate.getFullYear() - (todayDate.getFullYear() % 100)) + "-" + ((todayDate.getFullYear() - (todayDate.getFullYear() % 100)) + 100);
		}

		private function createTodayButton():void
		{

		}

		private function createTodayIndicator():void
		{

		}

		private function createSelectionIndicator():void
		{

		}

		private function createRollOverIndicator():void
		{

		}

		override protected function measure():void
		{
			super.measure();
		}

		private function monthClickHandler(event:MouseEvent):void
		{
			displayedMode=DateChooserModes.DATE;
			todayDate.setMonth(Number((event.currentTarget as LinkButton).name));
			createDayLayout();
		}

		private function yearClickHandler(event:MouseEvent):void
		{
			displayedMode=DateChooserModes.MONTH;
			todayDate.setFullYear(Number((event.currentTarget as LinkButton).label));
			createMonthLayout();
		}

		private function decadeClickHandler(event:MouseEvent):void
		{
			displayedMode=DateChooserModes.YEAR;
			todayDate.setFullYear(Number((event.currentTarget as Text).name));
			createYearLayout();
		}

		private function leftButtonHandler(event:Event):void
		{
			todayDate.setMonth(todayDate.getMonth() - 1);
			invalidateDisplayList();
		}

		private function middleButtonHandler(event:MouseEvent):void
		{
			if (displayedMode == DateChooserModes.DATE)
			{
				displayedMode=DateChooserModes.MONTH;
				createMonthLayout();
			}
			else if (displayedMode == DateChooserModes.MONTH)
			{
				displayedMode=DateChooserModes.YEAR;
				createYearLayout();
			}
			else if (displayedMode == DateChooserModes.YEAR)
			{
				displayedMode=DateChooserModes.DECADE;
				createDecadeLayout();
			}
		}

		private function rightButtonHandler(event:Event):void
		{
			todayDate.setMonth(todayDate.getMonth() + 1);
			invalidateDisplayList();
		}

		private function getDaysForMonthAndYear(year:Number, month:Number):Array
		{
			var days:Array=new Array();
			var numDaysInMonths:Array=[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
			//For leap
			if (year % 4 == 0)
				numDaysInMonths[1]=29;
			for (var i:int=0; i < numDaysInMonths[month]; i++)
			{
				days.push(i + 1);
			}
			return days;
		}

		private function getNumberOfDaysInMonth(year:int, month:int):int
		{
			var n:int;

			if (month == 1)
			{
				if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) // leap year
					n=29;
				else
					n=28;
			}

			else if (month == 3 || month == 5 || month == 8 || month == 10)
				n=30;

			else
				n=31;

			return n;
		}

		private function getOffsetOfMonth(year:int, month:int):int
		{
			var first:Date=new Date(year, month, 1);
			var offset:int=first.getDay() - _firstDayOfWeek;
			return offset < 0 ? offset + 7 : offset;
		}

		private function findFirstDayOfMonth(year:Number, month:Number):Number
		{
			var day:Number=new Date(year, month, 1).day;
			return day;
		}

		private function mouseOverHandler(event:MouseEvent):void
		{
			if (event.relatedObject && event.relatedObject.parent != this)
				addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			else
				event.stopImmediatePropagation();
		}

		private function mouseOutHandler(event:MouseEvent):void
		{
			if (event.relatedObject && event.relatedObject.parent != this)
			{

				removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
				rollOverIndicator.visible=false;
			}
			else
			{
				event.stopImmediatePropagation();
			}
		}

		/**
		 *  @private
		 */
		private function mouseMoveHandler(event:MouseEvent):void
		{
			var paddingLeft:Number=getStyle("paddingLeft");
			var paddingTop:Number=getStyle("paddingTop");

			var firstColX:Number=dayBlocksArray[0][0].x;
			var lastColX:Number=dayBlocksArray[6][0].x;
			var firstRowY:Number=dayBlocksArray[6][0].y + cellHeight;

			var mousePoint:Point=new Point(event.stageX, event.stageY);
			mousePoint=globalToLocal(mousePoint);
			var mouseY:Number=mousePoint.y;
			var mouseX:Number=mousePoint.x;

			if (mouseX < firstColX || mouseX > lastColX + cellWidth || mouseY < firstRowY)
				return;

			var rowIndex:int=Math.floor((mouseY - paddingTop) / cellHeight);
			var colIndex:int=Math.floor((mouseX - paddingLeft) / cellWidth);

			colIndex=Math.min(colIndex, 6);
			rowIndex=Math.min(rowIndex, 6);

			var selCell:IUITextField=dayBlocksArray[colIndex][rowIndex];

			if (mouseY >= selCell.y && mouseY <= selCell.y + cellHeight && mouseX >= selCell.x && mouseX <= selCell.x + cellWidth)
			{
				rollOverIndicator.move(selCell.x, selCell.y + yOffset);
				rollOverIndicator.visible=true;
			}
		}

		private function mouseUpHandler(event:MouseEvent):void
		{
			var paddingLeft:Number=getStyle("paddingLeft");
			var paddingTop:Number=getStyle("paddingTop");

			var firstColX:Number=dayBlocksArray[0][0].x;
			var lastColX:Number=dayBlocksArray[6][0].x;
			var firstRowY:Number=dayBlocksArray[6][0].y + cellHeight;

			var mousePoint:Point=new Point(event.stageX, event.stageY);
			mousePoint=globalToLocal(mousePoint);
			var mouseY:Number=mousePoint.y;
			var mouseX:Number=mousePoint.x;

			if (mouseX < firstColX && mouseX >= lastColX + cellWidth || mouseY < firstRowY)
				return;

			var rowIndex:int=Math.floor((mouseY - paddingTop) / cellHeight);

			if (rowIndex <= 0)
				return;
			rowIndex=Math.min(rowIndex, 6);

			var colIndex:int=Math.floor((mouseX - paddingLeft) / cellWidth);
			colIndex=Math.min(colIndex, 6);

			var selCell:IUITextField=dayBlocksArray[colIndex][rowIndex];

		}
		static private var dcis:Object={};

		static private function isDateChooserIndicator(parent:Object):Boolean
		{
			var s:String=getQualifiedClassName(parent);
			if (dcis[s] == 1)
				return true;

			if (dcis[s] == 0)
				return false;

			if (s == "mx.skins.halo::DateChooserIndicator")
			{
				dcis[s] == 1;
				return true;
			}

			var x:XML=describeType(parent);
			var xmllist:XMLList=x.extendsClass.(@type == "mx.skins.halo::DateChooserIndicator");
			if (xmllist.length() == 0)
			{
				dcis[s]=0;
				return false;
			}

			dcis[s]=1;
			return true;
		}
	}
}